package com.klm.easymq.aspect;

import com.klm.easymq.annotation.MQProducer;
import com.klm.easymq.core.MonitorService;
import com.klm.easymq.service.EasyMqService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.UUID;

/**
 * MQ生产者切面
 * 处理@MQProducer注解的消息生产逻辑
 */
@Aspect
@Component
@Slf4j
public class MQProducerAspect {

    @Autowired
    private EasyMqService easyMqService;

    @Autowired
    private MonitorService monitorService;

    private final ExpressionParser expressionParser = new SpelExpressionParser();
    private final DefaultParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();

    @Around("@annotation(mqProducer)")
    public Object aroundMQProducer(ProceedingJoinPoint joinPoint, MQProducer mqProducer) throws Throwable {
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        Object[] args = joinPoint.getArgs();
        
        // 生成traceId
        String traceId = generateTraceId();
        
        // 记录生产开始
        monitorService.recordMessageSend(traceId, mqProducer.topic(), "PRODUCING", "SENDING");
        
        try {
            // 执行原方法获取消息内容
            Object result = joinPoint.proceed();
            
            // 生成消息键
            String messageKey = generateMessageKey(mqProducer.key(), method, args);
            
            // 发送消息
            boolean sendResult = sendMessage(mqProducer, result, messageKey, traceId);
            
            // 记录发送结果
            String status = sendResult ? "SUCCESS" : "FAILED";
            monitorService.recordMessageSend(traceId, mqProducer.topic(), 
                    result != null ? result.toString() : "null", status);
            
            log.info("消息发送完成: topic={}, traceId={}, result={}", 
                    mqProducer.topic(), traceId, sendResult);
            
            return result;
            
        } catch (Exception e) {
            log.error("消息发送失败: topic={}, traceId={}", mqProducer.topic(), traceId, e);
            monitorService.recordMessageSend(traceId, mqProducer.topic(), "ERROR", "FAILED");
            throw e;
        }
    }

    /**
     * 发送消息
     */
    private boolean sendMessage(MQProducer mqProducer, Object message, String messageKey, String traceId) {
        try {
            String topic = mqProducer.topic();
            String tag = mqProducer.tag();
            int delayLevel = mqProducer.delayLevel();
            
            switch (mqProducer.sendMode()) {
                case SYNC:
                    return easyMqService.sendSync(topic, message, tag, messageKey);
                    
                case ASYNC:
                    easyMqService.sendAsync(topic, message, tag, messageKey);
                    return true;
                    
                case ONEWAY:
                    easyMqService.sendOneway(topic, message, tag, messageKey);
                    return true;
                    
                default:
                    return easyMqService.sendSync(topic, message, tag, messageKey);
            }
            
        } catch (Exception e) {
            log.error("发送消息异常: topic={}, traceId={}", mqProducer.topic(), traceId, e);
            return false;
        }
    }

    /**
     * 生成消息键
     */
    private String generateMessageKey(String expression, Method method, Object[] args) {
        if (expression.isEmpty()) {
            return UUID.randomUUID().toString();
        }
        
        try {
            String[] parameterNames = parameterNameDiscoverer.getParameterNames(method);
            EvaluationContext context = new StandardEvaluationContext();
            
            if (parameterNames != null) {
                for (int i = 0; i < parameterNames.length && i < args.length; i++) {
                    context.setVariable(parameterNames[i], args[i]);
                }
            }
            
            Expression exp = expressionParser.parseExpression(expression);
            Object result = exp.getValue(context);
            return result != null ? result.toString() : UUID.randomUUID().toString();
            
        } catch (Exception e) {
            log.warn("生成消息键失败，使用随机UUID: expression={}", expression, e);
            return UUID.randomUUID().toString();
        }
    }

    /**
     * 生成追踪ID
     */
    private String generateTraceId() {
        return UUID.randomUUID().toString();
    }
} 